﻿using ControlHelper.Tools;
using ControlHelper.WPF;
using Creator.Core.DataBind;
using Creator.Core.Entity;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static ControlHelper.ControlHepler;

namespace DesktopCreator.Controls
{
    /// <summary>
    /// UCPanelObjects.xaml 的交互逻辑
    /// </summary>
    public partial class UCPanelObjects : UserControl
    {

        List<BindConfig> bindConfigs = new List<BindConfig>();
        public UCPanelObjects()
        {
            InitializeComponent();
            bindConfigs = JsonHelper.ReadJson<List<BindConfig>>(Directory.GetCurrentDirectory() + @"\DataBindConfig.json", true);
            if (bindConfigs == null) bindConfigs = new List<BindConfig>();

            new UIElementMove(this, this.Parent as Window)
            {
                CanMove = true,
                CanWhell = true
            };
        }

        public UCPanelObjects(IList data) : this()
        {
            Init(data);
        }
        /// <summary>
        /// 这个是的泛型 ，T 是  <see cref="Creator.Core.Entity.IUIEntity"/>
        /// </summary>
        public IList Data { get; private set; }

        /// <summary>
        /// 加载数据控件
        /// </summary>
        /// <param name="data"></param>
        public void Init(IList data)
        {
            Data = data;
            foreach (var item in data)
            {
                canvasMain.Children.Add(CreateBaseUI(item));
            }
            var entitys = data.OfType<IUIEntity>();
            Width = canvasMain.Width = entitys.Max(a => a.PosX) + entitys.Where(a => a.PosX == entitys.Max(b => b.PosX)).First().Width;
            Height = canvasMain.Height = entitys.Max(a => a.PosY) + entitys.Where(a => a.PosY == entitys.Max(b => b.PosY)).First().Height;
        }

        /// <summary>
        /// 设置最新数据更新
        /// </summary>
        /// <param name="data"></param>
        public void SetData(IList data)
        {
            if (data == null || data.Count == 0) return;
            SetDataList(Data, data);
        }
         
        /// <summary>
        /// 创建基础显示UI
        /// </summary> 
        private FrameworkElement CreateBaseUI(object data)
        {
            Border mainBorder = new Border
            {
                Name = "mainBorder",
                CornerRadius = new CornerRadius(5),
                HorizontalAlignment = HorizontalAlignment.Left,
                VerticalAlignment = VerticalAlignment.Top, 
            };

            Popup popup = new Popup();
            StackPanel panel = new StackPanel()
            {
                Background = new SolidColorBrush(Colors.White),
            };
            CreateBind(data, panel);
            popup.Child = panel;

            mainBorder.MouseEnter += (s, e) =>
            {
                popup.IsOpen = true;
            };
            mainBorder.MouseLeave += (s, e) =>
            {
                popup.IsOpen = false;
            };

            Grid mainGrid = new Grid();
             
            Grid innerGrid = new Grid
            {
                Margin = new Thickness(3),
            };

            Border borderStatus = new Border
            {
                Name = "borderStatus",
                Background = new SolidColorBrush(Color.FromRgb(125, 234, 234)),
                CornerRadius = new CornerRadius(3),
            };

            StackPanel stackPanel = new StackPanel
            {
                VerticalAlignment = VerticalAlignment.Center,
            };

            TextBlock txtTitle = new TextBlock
            {
                Name = "txtTitle",
                FontSize = 7,
                Text = "xxx",
                TextWrapping = TextWrapping.Wrap,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
            };

            TextBlock txtDir = new TextBlock
            {
                Name = "txtDir",
                FontSize = 7,
                Text = "ddd",
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
            };

            // Add the controls to the hierarchy
            stackPanel.Children.Add(txtTitle);
            stackPanel.Children.Add(txtDir);

            borderStatus.Child = stackPanel;
            innerGrid.Children.Add(borderStatus);

            mainGrid.Children.Add(innerGrid);
            mainGrid.Children.Add(popup);
            mainBorder.Child = mainGrid;
            if (data is IUIEntity eneity)
            {
                mainBorder.Width = eneity.Width;
                mainBorder.Height = eneity.Height;
                mainBorder.RenderTransform = new TranslateTransform(eneity.PosX, eneity.PosY);

                txtTitle.Text = eneity.Name;
                txtTitle.DataContext = data;
                txtTitle.SetBinding(TextBlock.TextProperty, CreateBinding(nameof(eneity.Name), bindingMode: BindingMode.OneWay));


                txtDir.Text = eneity.RealTimeInfo;
                txtDir.DataContext = data;
                txtDir.SetBinding(TextBlock.TextProperty, CreateBinding(nameof(eneity.RealTimeInfo)));
            }
            return mainBorder;
        }
        /// <summary>
        /// 创建这个类型绑定配置 添加到一个容器上
        /// </summary> 
        private void CreateBind(object data, Panel fe)
        {
            //找到对应类型的绑定配置
            var config = bindConfigs.Where(a => a.TargetType == data.GetType()).FirstOrDefault();
            if (config == null) return;
            foreach (var bind in config.Binds)
            {
                StackPanel panel = new StackPanel()
                {
                    Orientation = Orientation.Horizontal
                };

                TextBlock textBlock = new TextBlock();
                textBlock.Text = bind.PropertyName;
                textBlock.TextAlignment = TextAlignment.Center;

                TextBlock txt = new TextBlock();
                txt.TextAlignment = TextAlignment.Center;
                txt.Margin = new Thickness(10, 0, 0, 0);
                SetDataBind(txt, data, bind);
                panel.Children.Add(textBlock);
                panel.Children.Add(txt);
                fe.Children.Add(panel);
            }
        }

        /// <summary>
        /// 设置数据绑定
        /// </summary> 
        private void SetDataBind(FrameworkElement fe, object dataContext, BindProperty bindItem)
        {
            if (dataContext == null || fe == null) return;

            fe.DataContext = dataContext;
            var dp = GetDependencyProperty(bindItem.PropertyType);
            fe.SetBinding(dp, CreateBinding(bindItem.PropertyName));
        } 
        /// <summary>
        /// 设置集合数据进行变动,集合中的元素必须继承于<see cref="Creator.Core.Entity.IUIEntity"/>
        /// </summary> 
        private void SetDataList(IList oldData, IList newData)
        {
            if (oldData == null || newData == null)return;  
            if (oldData.Count != newData.Count) return;
            var oldDic = oldData.OfType<IUIEntity>().ToDictionary(a => a.IdHashCode, b => b);
            var newList = newData.OfType<IUIEntity>();

            foreach (var newItem in newList)
            {
                if (!oldDic.TryGetValue(newItem.IdHashCode, out var oldItem)) continue;
                SetData(oldItem, newItem);
            }
        } 
        /// <summary>
        /// 设置新的数据，取决于有没有做绑定配置<see cref="Creator.Core.DataBind.BindConfig"/>
        /// </summary> 
        private void SetData(object oldData, object newData)
        {
            if (newData == null) return;
            //获取类型的绑定配置
            var bind = bindConfigs.Where(a => a.TargetType == newData.GetType()).FirstOrDefault();
            if (bind == null) return;
            var newType = newData.GetType();
            var oldType = oldData.GetType();
            foreach (var item in bind.Binds)
            {
                //获取新数据的属性信息
                var newProperty = newType.GetProperty(item.PropertyName);
                if (newProperty == null) continue;
                //获取老数据的属性信息
                var oldProp = oldType.GetProperty(item.PropertyName);
                if(oldProp == null || oldProp.SetMethod == null) continue;
                oldProp.SetValue(oldData, newProperty.GetValue(newData));
            }
        }
         
        /// <summary>
        /// 设置新的数据，找到相同的属性名称才去set
        /// </summary> 
        private void SetDataByAllProperty(object oldData, object newData)
        {
            if (oldData == null || newData == null) return;
            var oldProps = oldData.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var pro in oldProps)
            { 
                var newProp = newData.GetType().GetProperty(pro.Name);
                var value = newProp.GetValue(newData);
                if (pro.SetMethod == null) continue;
                pro.SetValue(oldData, value); 
            }
        }
    }
}
